package com.cherry.androidcode.okgo

import com.cherry.androidcode.entity.HttpResult
import com.cherry.androidcode.entity.SimpleResponse
import com.google.gson.stream.JsonReader
import com.lzy.okgo.convert.Converter
import okhttp3.Response
import org.json.JSONArray
import org.json.JSONObject
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class JsonConvert<T>(private var type: Type? = null,
                              private var clazz: Class<T>? = null) : Converter<T> {

    constructor() : this(null, null)

    /**
     * 该方法是子线程处理，不能做ui相关的工作
     * 主要作用是解析网络返回的 response 对象，生成onSuccess回调中需要的数据对象
     */
    @Throws(Throwable::class)
    override fun convertResponse(response: Response): T? {
        if (type == null) {
            if (clazz == null) {
                // 如果没有通过构造函数传进来，就自动解析父类泛型的真实类型（有局限性，继承后就无法解析到）
                val genType = javaClass.genericSuperclass
                type = (genType as? ParameterizedType)?.actualTypeArguments?.get(0)
            } else {
                return parseClass(response, clazz)
            }
        }
        return when (type) {
            is ParameterizedType -> parseParameterizedType(response, type as ParameterizedType?)
            is Class<*> -> parseClass(response, type as Class<*>?)
            else -> parseType(response, type)
        }
    }

    @Suppress("UNCHECKED_CAST")
    @Throws(Exception::class)
    private fun parseClass(response: Response, rawType: Class<*>?): T? {
        if (rawType == null) return null
        val body = response.body() ?: return null
        val jsonReader = JsonReader(body.charStream())

        return when (rawType) {
            String::class.java -> body.string() as? T
            JSONObject::class.java -> JSONObject(body.string()) as? T
            JSONArray::class.java -> JSONArray(body.string()) as? T
            else -> {
                val t = Convert.fromJson<T>(jsonReader, rawType)
                response.close()
                t
            }
        }
    }

    @Throws(Exception::class)
    private fun parseType(response: Response, type: Type?): T? {
        if (type == null) return null
        val body = response.body() ?: return null
        val jsonReader = JsonReader(body.charStream())

        // 泛型格式如下： new JsonCallback<任意JavaBean>(this)
        val t = Convert.fromJson<T>(jsonReader, type)
        response.close()
        return t
    }

    @Suppress("UNCHECKED_CAST")
    @Throws(Exception::class)
    private fun parseParameterizedType(response: Response, type: ParameterizedType?): T? {
        if (type == null) return null
        val body = response.body() ?: return null
        val jsonReader = JsonReader(body.charStream())

        val rawType = type.rawType                     // 泛型的实际类型
        val typeArgument = type.actualTypeArguments[0] // 泛型的参数
        if (rawType !== HttpResult::class.java) {
            // 泛型格式如下： new JsonCallback<外层BaseBean<内层JavaBean>>(this)
            val t = Convert.fromJson<T>(jsonReader, type)
            response.close()
            return t
        } else {
            if (typeArgument === Void::class.java) {
                // 泛型格式如下： new JsonCallback<HttpResult<Void>>(this)
                val simpleResponse = Convert.fromJson<SimpleResponse>(jsonReader, SimpleResponse::class.java)
                response.close()

                return simpleResponse.toHttpResponse() as? T
            } else {
                // 泛型格式如下： new JsonCallback<HttpResult<内层JavaBean>>(this)
                val httpResponse = Convert.fromJson<HttpResult<*>>(jsonReader, type)
                response.close()
                val code = httpResponse.status
                //这里的0是以下意思
                //一般来说服务器会和客户端约定一个数表示成功，其余的表示失败，这里根据实际情况修改
                return if (code == 0) {
                    httpResponse as? T
                } else {
                    //直接将服务端的错误信息抛出，onError中可以获取
                    throw IllegalStateException("错误代码：" + code + "，错误信息：" + httpResponse.msg)
                }
            }
        }
    }
}
